import pandas as pd
import os,random
import os,subprocess,time
from datetime import date
import pandas as pd
import logging,codecs
#-*- coding=utf-8 -*-

def ReadFile(filePath):
    with codecs.open(filePath, "r") as f:
        return f.read()
def WriteFile(filePath, u, encoding="utf-8"):
    # with codecs.open(filePath,"w",encoding) as f:
    with codecs.open(filePath, "wb") as f:
        f.write(u.encode(encoding, errors="ignore"))
def CSV_2_UTF8(src, dst):
    content = ReadFile(src)
    WriteFile(dst, content, encoding="utf-8")

def  每手取整(代码,数量,仓位):
    if 代码[0:2]!="68":
        取整数量=round(数量*仓位,-2)
    elif 代码[0:2]=="68":
        取整数量=round(数量*仓位,0)   
    return 取整数量

#  指定目录下，将数据带时间后缀保存为csv格式
def saveCsvByTime(fileNanme,saveData,TimeFlag):
    # OQPath:导出目录，fileNanme：文件名前缀，saveData：保存的数据
    now = datetime.datetime.now()
    if TimeFlag==True:
        filename = f"{fileNanme}_{now.strftime('%Y-%m-%d_%H-%M-%S')}.csv"
    else:
        filename = f"{fileNanme}.csv"
    full_path = joinPath(filename)
    saveData.to_csv(full_path,index=False)
    
#记录日志到本地
def logfun(isfile=True):
    # black, red, green, yellow, blue, purple, cyan(青) and white, bold(亮白色)
    log_colors_config = {
        'DEBUG': 'bold_white',
        'INFO': 'bold',
        'WARNING': 'yellow',
        'ERROR': 'red',
        'CRITICAL': 'bold_red', # 加bold后色彩变亮
    }
    logger = logging.getLogger()
    # 输出到console
    # logger.setLevel(level=logging.DEBUG)
    logger.setLevel(level=logging.INFO) # 某些python库文件中有一些DEBUG级的输出信息，如果这里设置为DEBUG，会导致console和log文件中写入海量信息

    console = logging.StreamHandler()  # 输出到console的handler
    console.setLevel(logging.INFO)
    console.setFormatter(console_formatter)
    logger.addHandler(console)
    # 输出到文件
    if isfile:
        # 设置文件名
        now = datetime.datetime.now()
        filename = f"log_{now.strftime('%Y-%m-%d_%H-%M-%S')}.txt"
        log_path=os.path.join(os.getcwd(),'log')
        if not os.path.exists(log_path):
            os.mkdir(log_path)
        logfile = log_path + '/'+filename
        # 设置文件日志格式
        filer = logging.FileHandler(logfile,mode='w') # 输出到log文件的handler
        # filer.setLevel(level=logging.DEBUG)
        file_formatter = logging.Formatter(
            fmt='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
            datefmt='%Y-%m-%d  %H:%M:%S'
        )
        # formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
        filer.setFormatter(file_formatter)
        logger.addHandler(filer)

    return logger

#生成自动化执行清单，资金账号按&连接
def 生成执行表单(资金账号列表,账号类型列表,自动导出目录):

    # 登录成功后，从自动导出获取交易数据列表并转化成可执行清单列表
    资金账号列表=资金账号列表.split("&")
    账号类型列表=账号类型列表.split("&")
    CSV_2_UTF8(os.path.join(自动导出目录,"positionInfo_"+date.today().strftime("%Y%m%d")+".csv"), os.path.join(自动导出目录,"positionInfo_"+date.today().strftime("%Y%m%d")+"_utf.csv"))
    CSV_2_UTF8(os.path.join(自动导出目录,"enslo_"+date.today().strftime("%Y%m%d")+".csv"), os.path.join(自动导出目录,"enslo_"+date.today().strftime("%Y%m%d")+"_utf.csv"))
    CSV_2_UTF8(os.path.join(自动导出目录,"compactInfo_"+date.today().strftime("%Y%m%d")+".csv"), os.path.join(自动导出目录,"compactInfo_"+date.today().strftime("%Y%m%d")+"_utf.csv"))
    持仓列表=pd.read_csv(os.path.join(自动导出目录,"positionInfo_"+date.today().strftime("%Y%m%d")+"_utf.csv"))
    持仓列表.drop(持仓列表.tail(1).index,inplace=True)  #删除最后一行换行
    持仓列表["账号"]=持仓列表["账号"].astype('int64').astype('str')
    融券标的=pd.read_csv(os.path.join(自动导出目录,"enslo_"+date.today().strftime("%Y%m%d")+"_utf.csv"))
    融券标的.drop(融券标的.tail(1).index,inplace=True)
    融券标的["账号"]=融券标的["账号"].astype('int64').astype('str')
    融资融券合约=pd.read_csv(os.path.join(自动导出目录,"compactInfo_"+date.today().strftime("%Y%m%d")+"_utf.csv"))
    融资融券合约.drop(融资融券合约.tail(1).index,inplace=True)
    融资融券合约["账号"]=融资融券合约["账号"].astype('int64').astype('str')
    执行清单=pd.DataFrame(columns=['菜单', '账号','账号类型', '证券代码', '开仓方向', '平仓方向', '总委托数量', '多轮执行次数', '持仓数量','普通卖出可用数', '卖券还款可用数', '未还融资数量', '未还融券数量',  '融券可用头寸','最大可执行总量','启用'])
    i=0
    for 资金账号 in 资金账号列表:
        i=i+1
        if 资金账号[0:4]!="8888":
            #为股票账户，生成买入、卖出组合，只输出可用数量前10的
            资金账号持仓信息=持仓列表[持仓列表["账号"]==资金账号].sort_values(by="可用数量",ascending=False, inplace=False).head(10)
            for 证券代码 in 资金账号持仓信息["securityID"]:
                最大可执行总量=资金账号持仓信息[资金账号持仓信息["securityID"]==证券代码]["可用数量"].iloc[0]
                总委托数量=每手取整(证券代码,最大可执行总量,0.33)
                持仓数量=资金账号持仓信息[资金账号持仓信息["securityID"]==证券代码]["当前数量"].iloc[0]
                普通卖出可用数=最大可执行总量
                卖券还款可用数=0
                未还融资数量=0
                未还融券数量=0
                融券可用头寸=0
                执行指令=["手工T0",资金账号,账号类型列表[i],证券代码,"买入","卖出",总委托数量, '5', 持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量,融券可用头寸, 最大可执行总量,'Y']
                执行列表=pd.DataFrame(执行指令)
                执行清单=pd.concat([执行清单,执行列表])
                执行指令=["传统模式",资金账号,账号类型列表[i],证券代码,"买入","卖出",总委托数量, '5', 持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量, 最大可执行总量,'Y']
                执行列表=pd.DataFrame(执行指令)
                执行清单=pd.concat([执行清单,执行列表])
        else :
            print(持仓列表[持仓列表["账号"]==资金账号 and 持仓列表["可用数量"]>0])
            资金账号持仓信息=持仓列表[持仓列表["账号"]==资金账号 and 持仓列表["可用数量"]>0].sort_values(by="可用数量",ascending=False, inplace=False)

            if 账号类型列表[i]=="极速两融":
                可融券标的列表=融券标的[融券标的["账号"]==资金账号 and 融券标的["专项可融头寸"]>0].sort_values(by="专项可融头寸",ascending=False, inplace=False)
            elif 账号类型列表[i]=="普通两融":
                可融券标的列表=融券标的[融券标的["账号"]==资金账号 and 融券标的["普通可融头寸"]>0].sort_values(by="普通可融头寸",ascending=False, inplace=False)
            未还融券负债=融资融券合约[融资融券合约["账号"]==资金账号 and 融资融券合约["合约状态"]in["0","1"] and 融资融券合约["compactType"]=="1" and 融资融券合约["未还合约数量"]>0].sort_values(by="未还合约数量",ascending=False, inplace=False)
            未还融资负债=融资融券合约[融资融券合约["账号"]==资金账号 and 融资融券合约["合约状态"]in["0","1"] and 融资融券合约["compactType"]=="0" and 融资融券合约["未还合约数量"]>0].sort_values(by="未还合约数量",ascending=False, inplace=False)
            #满足可用>0的代码交集(有融券头寸和持仓)
            可融券标的列表["securityID"].tolist().intersection(资金账号持仓信息["securityID"].tolist())
            #为信用账户，生成融券卖出、现券还券组合，只输出前10的
            买卖组合=["融券卖出现券还券","融券卖出买券还券","普通卖出融资买入","普通卖出普通买入","卖券还款融资买入","卖券还款普通买入"]
            for 证券代码 in 可融券标的列表:
                未还融资数量=未还融资负债[未还融资负债["账号"]==资金账号 and 未还融资负债["securityID"]==证券代码]["未还合约数量"].sum()
                未还融券数量=未还融券负债[未还融券负债["账号"]==资金账号 and 未还融券负债["securityID"]==证券代码]["未还合约数量"].sum()
                持仓数量=资金账号持仓信息[资金账号持仓信息["securityID"]==证券代码]["当前数量"].iloc[0]
                卖券还款可用数=未还融资数量
                普通卖出可用数=资金账号持仓信息[资金账号持仓信息["securityID"]==证券代码]["可用数量"].iloc[0]-卖券还款可用数
                if 账号类型列表[i]=="极速两融":
                    融券可用头寸=融券标的[融券标的["账号"]==资金账号 and 融券标的["securityID"]==证券代码]["专项可融头寸"].iloc[0]
                elif 账号类型列表[i]=="普通两融":
                    融券可用头寸=融券标的[融券标的["账号"]==资金账号 and 融券标的["securityID"]==证券代码]["普通可融头寸"].iloc[0]
                for 组合 in 买卖组合:
                    if 组合=="融券卖出现券还券":
                        最大可执行总量=min(未还融券数量,持仓数量,融券可用头寸)
                        总委托数量=每手取整(证券代码,最大可执行总量,0.33)
                        执行指令=["手工T0",资金账号,账号类型列表[i],证券代码,"融券卖出","现券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量,融券可用头寸, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])
                        执行指令=["传统模式",资金账号,账号类型列表[i],证券代码,"融券卖出","现券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])                   
                    
                    elif 组合=="融券卖出买券还券":
                        最大可执行总量=min(未还融券数量,融券可用头寸)
                        总委托数量=每手取整(证券代码,最大可执行总量,0.33)
                        执行指令=["手工T0",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量,融券可用头寸, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])
                        执行指令=["传统模式",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])   
                    elif 组合=="普通卖出融资买入":
                        最大可执行总量=普通卖出可用数
                        总委托数量=每手取整(证券代码,最大可执行总量,0.33)
                        执行指令=["手工T0",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量,融券可用头寸, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])
                        执行指令=["传统模式",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])
                    elif 组合=="普通卖出普通买入":
                        最大可执行总量=普通卖出可用数
                        总委托数量=每手取整(证券代码,最大可执行总量,0.33)
                        执行指令=["手工T0",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量,融券可用头寸, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])
                        执行指令=["传统模式",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])                      
                    elif 组合=="卖券还款融资买入":
                        最大可执行总量=卖券还款可用数
                        总委托数量=每手取整(证券代码,最大可执行总量,0.33)
                        执行指令=["手工T0",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量,融券可用头寸, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])
                        执行指令=["传统模式",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])   
                    elif 组合=="卖券还款普通买入":
                        最大可执行总量=卖券还款可用数
                        总委托数量=每手取整(证券代码,最大可执行总量,0.33)
                        执行指令=["手工T0",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量,融券可用头寸, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表])
                        执行指令=["传统模式",资金账号,账号类型列表[i],证券代码,"融券卖出","买券还券",总委托数量, '5',  持仓数量,普通卖出可用数, 卖券还款可用数, 未还融资数量, 未还融券数量, 最大可执行总量,'Y']
                        执行列表=pd.DataFrame(执行指令)
                        执行清单=pd.concat([执行清单,执行列表]) 
    saveCsvByTime("T0执行清单",执行清单,True)
    
    
生成执行表单("880100001139&888821600235","极速股票&极速两融","C:\Ax\安信OneQuant\Data",)


    
    

#启动客户端，打开对应的功能菜单
def 启动客户端(客户端目录地址,账号类型,交易账号,交易密码):
    pass




#打开手工T0页面下单，处理后关闭窗口
def 手工T0(代码,买入方向,卖出数量,买卖超价,买卖数量,运行次数):
    pass





#打开传统模式页面下单，处理后关闭窗口
def 传统模式(代码,交易方向,买卖超价,买卖数量,运行次数):
    pass


























